package principal;

import java.awt.Component;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Iterator;
import java.util.List;


public class ReconocedorEventos implements IReconocedorFormas {

	private Trazo t;

	
	public void setTrazo(Trazo t) {
		this.t = t;
	}
	
	public int reconoceTrazo() {
		if(t.getAchura()<8)
			return 3;
		if(t.getAltura()<8)
			return 4;
		
		Point centro = getCentroMasa(t);
		
		Recta vert = new Recta(1,0,-(int)centro.getX());
		Recta hori = new Recta(0,1,-(int)centro.getY());
		
		Recta diag1 = new Recta(1,-1,-centro.x+centro.y);
		Recta diag2 = new Recta(1,1,-centro.x-centro.y);
		
		List puntos_arriba = t.getPuntosArriba(centro); 
		List puntos_abajo = t.getPuntosAbajo(centro);
		List puntos_derecha = t.getPuntosDerecha(centro);
		List puntos_izquierda = t.getPuntosIzquierda(centro);
		
		Point2D punto1 = obtenerCorte(vert,puntos_arriba);
		double distancia1 = distancia(centro, punto1);
		
		Point2D punto2 = obtenerCorte(diag1,puntos_arriba);
		double distancia2 = distancia(centro, punto2); 
		
		Point2D punto3 = obtenerCorte(hori,puntos_derecha);
		double distancia3 = distancia(centro, punto3);
		
		Point2D punto4 = obtenerCorte(diag2,puntos_abajo);
		double distancia4 = distancia(centro, punto4);
		
		Point2D punto5 = obtenerCorte(vert,puntos_abajo);
		double distancia5 = distancia(centro, punto5);
		
		Point2D punto6 = obtenerCorte(diag1,puntos_abajo);
		double distancia6 = distancia(centro, punto6);
		
		Point2D punto7 = obtenerCorte(hori,puntos_izquierda);
		double distancia7 = distancia(centro, punto7);
		
		Point2D punto8 = obtenerCorte(diag2,puntos_arriba);
		double distancia8 = distancia(centro, punto8);
		
		double distancia_maxima = maximo(distancia1,distancia2,distancia3,distancia4,distancia5,distancia6,distancia7,distancia8);
		
		//normalizamos las distancias y las guardamos en un vector:
		
		double[] distancias = new double[8];
		
		distancias[0]= distancia1 / distancia_maxima;
		distancias[1] = distancia2 / distancia_maxima;
		distancias[2] = distancia3 / distancia_maxima;
		distancias[3] = distancia4 / distancia_maxima;
		distancias[4] = distancia5 / distancia_maxima;
		distancias[5] = distancia6 / distancia_maxima;
		distancias[6] = distancia7 / distancia_maxima;
		distancias[7] = distancia8 / distancia_maxima;

		double sim_sobre = similitud_sobre(distancias);
		double sim_reloj = similitud_reloj(distancias);

		
		double valor_opcion = sim_sobre;
		int ret = 1;//1, codigo para actividad
		
		if(valor_opcion>sim_reloj){
			valor_opcion = sim_reloj;
			ret = 2;//2, codigo para documento
		}
		
		return ret;
	}

	private double similitud_reloj(double[] distancias) {
		// TODO Auto-generated method stub
		double[] diferencias = new double[8];
		diferencias[0]=Math.abs(distancias[0]-1);
		diferencias[1]=Math.abs(distancias[1]-1);
		diferencias[2]=Math.abs(distancias[2]-1);
		diferencias[3]=Math.abs(distancias[3]-1);
		diferencias[4]=Math.abs(distancias[4]-1);
		diferencias[5]=Math.abs(distancias[5]-1);
		diferencias[6]=Math.abs(distancias[6]-1);
		diferencias[7]=Math.abs(distancias[7]-1);
		
		return media_distancias(diferencias);
	}
	private double media_distancias(double[] distancias) {
		double suma = 0;
		for(int i=0;i<distancias.length;i++)
			suma+=distancias[i];
		return suma/distancias.length;
	}
	private double similitud_sobre(double[] distancias) {
		// TODO Auto-generated method stub
		double[] diferencias = new double[8];
		diferencias[0]=Math.abs(distancias[0]-0.5);
		diferencias[1]=Math.abs(distancias[1]-0.7);
		diferencias[2]=Math.abs(distancias[2]-1);
		diferencias[3]=Math.abs(distancias[3]-0.7);
		diferencias[4]=Math.abs(distancias[4]-0.5);
		diferencias[5]=Math.abs(distancias[5]-0.7);
		diferencias[6]=Math.abs(distancias[6]-1);
		diferencias[7]=Math.abs(distancias[7]-0.7);
		
		return media_distancias(diferencias);
	}
	private double similitud_documento(double[] distancias) {
		// TODO Auto-generated method stub
		double[] diferencias = new double[8];
		diferencias[0]=Math.abs(distancias[0]-1);
		diferencias[1]=Math.abs(distancias[1]-0.7);
		diferencias[2]=Math.abs(distancias[2]-0.5);
		diferencias[3]=Math.abs(distancias[3]-0.7);
		diferencias[4]=Math.abs(distancias[4]-1);
		diferencias[5]=Math.abs(distancias[5]-0.7);
		diferencias[6]=Math.abs(distancias[6]-0.5);
		diferencias[7]=Math.abs(distancias[7]-0.7);
		
		return media_distancias(diferencias);
	}
	private double maximo(double distancia1, double distancia2,
			double distancia3, double distancia4, double distancia5,
			double distancia6, double distancia7, double distancia8) {
		// TODO Auto-generated method stub
		double max = distancia1;
		if(distancia2>max)
			max=distancia2;
		if(distancia3>max)
			max=distancia3;
		if(distancia4>max)
			max=distancia4;
		if(distancia5>max)
			max=distancia5;
		if(distancia6>max)
			max=distancia6;
		if(distancia7>max)
			max=distancia7;
		if(distancia8>max)
			max=distancia8;
		
		return max;
	}
	private double distancia(Point centro, Point2D punto1) {
		double dx = Math.pow((centro.getX()-punto1.getX()),2);
		double dy = Math.pow((centro.getY()-punto1.getY()),2);
		double res = Math.sqrt(dx+dy);
		return res;
	}
	//Itero sobre la lista de puntos hasta encontrar uno que pertenezca a la recta
	/* 
	 * NOTA: La lista depuntos no es continua, busco el punto de menor dsitancia a 
	 * la recta, suponiendo que este es el corte 
	 */
	private Point2D obtenerCorte(Recta r, List<Point2D> puntos_arriba) {
		// TODO Auto-generated method stub
		double min_dist = Double.MAX_VALUE;
		Iterator<Point2D> it = puntos_arriba.iterator();
		Point2D tmp,ret = null;
		double dist_act;
		while(it.hasNext()){
			tmp = (Point2D)it.next();
			dist_act = r.distancia(tmp);
			if(dist_act<min_dist){
				min_dist = dist_act;
				ret = tmp;
			}
		}
		return ret;
	}

	public Point getCentroMasa(Trazo t){
		
		int coordX = (t.get_punto_mas_der()+t.get_punto_mas_izq())/2; 
		int coordY = (t.get_punto_mas_bajo()+t.get_punto_mas_alto())/2;
		Point res = new Point(coordX, coordY);
		
		return res;
		
	}

	@Override
	public String reconoceEscritura(Component c) {
		// TODO Auto-generated method stub
		return null;
	}

}

